/* eslint-disable react-hooks/exhaustive-deps */
import { Button, Mask, SafeArea } from 'antd-mobile'
import React, { useState, useEffect, useRef } from 'react'
import ReactDOM from 'react-dom'
import Cropper from 'react-easy-crop'
import cameraIcon from '@/static/image/camera_icon.png'
import type { BaseUploadInterface } from './BaseUpload'
import BaseUpload from './BaseUpload'
import getCroppedImg from './utils/cropImage'
import styles from './index.module.less'

/**
 * 图片裁剪组件
 *      在 beforeUpload 中 添加裁剪功能 其他字段参考 ImageUploader
 */

function CropImageUpload({ children, queryParams, ...props }: Omit<BaseUploadInterface, 'beforeUpload'>) {
    function fnCropImage(file: File): Promise<File> {
        return new Promise((resolve, reject) => {
            CropImageUpload.show({
                file,
                onOk(cropFile: File) {
                    return resolve(cropFile)
                },
                onCancel() {
                    return reject()
                },
            })
        })
    }

    return (
        <BaseUpload beforeUpload={fnCropImage} maxCount={1} {...props} queryParams={{ type: 'avatar', ...queryParams }}>
            {children || (
                <div className={styles.upload_btn}>
                    <img src={cameraIcon} alt="" />
                </div>
            )}
        </BaseUpload>
    )
}

interface CropImageUploadProps {
    file: File
    onOk: (file: File) => void
    onCancel: () => void
}

/** 展示裁剪模块 */
CropImageUpload.show = ({ file, onOk, onCancel }: CropImageUploadProps) => {
    const container = document.createElement('div')
    document.body.appendChild(container)

    /** 卸载组件 */
    const unmount = () => {
        if (container && container.parentNode) {
            container.parentNode.removeChild(container)
        }
    }

    /** 裁剪组件 */
    const Wrapper = () => {
        const [image, setImage] = useState<string>()
        const [bVisible, setBVisible] = useState(false)
        const [crop, setCrop] = useState({ x: 0, y: 0 })
        const [nZoom, setNZoom] = useState(1)
        const previewCanvas = useRef<HTMLCanvasElement>(null)
        const [areaPixels, setAreaPixels] = useState<{ x: any; y: any; width: any; height: any }>()

        useEffect(() => {
            const reader = new FileReader()
            reader.addEventListener('load', () => {
                if (typeof reader.result === 'string') {
                    setImage(reader.result)
                    setBVisible(true)
                }
            })
            reader.readAsDataURL(file)
        }, [file])

        /** 剪裁区域修改事件 * */
        const fnCropChange = async (_croppedArea: any, croppedAreaPixels: any) => {
            setAreaPixels(croppedAreaPixels)
        }

        /** 确定事件 */
        async function fnOnSubmit() {
            if (previewCanvas.current && image && areaPixels) {
                try {
                    const img = await getCroppedImg(previewCanvas?.current, image, areaPixels, 0)
                    const { name, type, uid } = file as any
                    if (img) {
                        const newFile = Object.assign(new File([img], name, { type }), { uid })
                        onOk(newFile)
                    }
                    unmount()
                } catch (e) {
                    console.error(e)
                }
            }
        }

        function fnOnCropCancel() {
            onCancel()
            unmount()
        }

        return (
            <Mask visible={bVisible} opacity={1}>
                <Cropper
                    image={image}
                    crop={crop}
                    rotation={0}
                    zoom={nZoom}
                    aspect={1}
                    onCropChange={setCrop}
                    classes={{ cropAreaClassName: styles['crop-window'] }}
                    onCropAreaChange={fnCropChange}
                    onZoomChange={setNZoom}
                />
                <div className={styles['crop-options-wrapper']}>
                    <Button onClick={fnOnCropCancel} fill="none">
                        取消
                    </Button>
                    <Button onClick={fnOnSubmit} fill="none">
                        完成
                    </Button>
                    <SafeArea position="bottom" />
                </div>
                <canvas ref={previewCanvas} />
            </Mask>
        )
    }
    ReactDOM.render(<Wrapper />, container)
}
export default CropImageUpload
